/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include <stdio.h>
#include <string.h>
#include <flgrCoreMalloc.h>
#include <flgrCoreData.h>
#include <flgrCoreDataIO.h>
#include <flgrCoreIO.h>
#include <flgrCoreCopy.h>
#include <flgrCoreSlideWindow.h>
#include <flgrCoreNhbManage.h>
#include <flgrCoreDispatch.h>
#include <flgrDataToolsFifo.h>

#include "flgrMorphoWatershedSPP1.h"


#define FLGR_MACRO_WATERSHED_SPP1_2D(dtype,dtypename,NB_FIFO)		\
  FLGR_Data2D *nhbOdd,*nhbEven;						\
  FLGR_Data2D *nhb;							\
  FLGR_NhbBox2D *cont;							\
  FLGR_Fifo fifo[NB_FIFO];						\
  int *cont_list_x;							\
  int *cont_list_y;							\
  dtype **label_ptr = (dtype**) imlabel->array;				\
  dtype **src_ptr = (dtype**) imsrc->array;				\
  dtype *cont_ptr;							\
  dtype *cont_center_ptr;						\
  dtype newcolor;							\
  dtype val;								\
  int i,j,w2,h2;							\
  int x, y, z;								\
  int m,n;								\
									\
  /***********************/						\
  /* Init priority Fifo */						\
  /***********************/						\
  for(i=0 ; i<NB_FIFO ; i++) {						\
    flgr_fifo_init(fifo+i);						\
  }									\
									\
  /********************************************/			\
  /* Fill Priority Fifo with src pixels */				\
  /********************************************/			\
  for(i=0 ; i<imsrc->size_y ; i++) {					\
    for(j=0 ; j<imsrc->size_x ; j++) {					\
      									\
      if(flgr2d_get_data_array_##dtype(label_ptr,i,j) > 0) {		\
      									\
	val = flgr2d_get_data_array_##dtype(src_ptr,i,j);		\
	flgr_fifo_push(fifo+val, 0, i, j);				\
      									\
      }									\
 									\
    }									\
  }									\
									\
  /************************/						\
  /* immersion simulation */						\
  /************************/						\
  nhb = flgr2d_create_neighborhood_from_connexity(imsrc->spp,		\
						  dtypename,		\
						  connexity);		\
									\
  nhbOdd = flgr2d_create_neighborhood_from(nhb);			\
  nhbEven = flgr2d_create_neighborhood_from(nhb);			\
  									\
  flgr2d_fill_nhbs_for_6_connexity(nhbEven,nhbOdd,nhb,FLGR_NHB_NO_SYM);	\
  									\
  flgr2d_destroy(nhb);							\
									\
  cont = flgr2d_create_neighbor_box(nhbOdd);				\
									\
  w2 = cont->nhb_size_x >> 1;						\
  h2 = cont->nhb_size_y >> 1;						\
									\
  cont_list_x = cont->list_coord_x[0];					\
  cont_list_y = cont->list_coord_y[0];					\
  cont_ptr = (dtype*) cont->list_data_val[0];				\
  cont_center_ptr = (dtype*) cont->center_data_val->array;		\
									\
									\
  for(i=1 ; i<NB_FIFO ; i++) {						\
    while( flgr_fifo_get_size(fifo+i) > 0) {				\
									\
      flgr_fifo_pop(fifo+i, &z, &y, &x);				\
									\
      nhb = ((y%2)==1 ? nhbOdd : nhbEven);				\
									\
      flgr2d_get_neighborhood_##dtype(cont,imlabel,nhb, y, x);		\
									\
      for(j=0 ; j<cont->size[0] ; j++) {				\
	n=y+cont_list_y[j]-h2;						\
	m=x+cont_list_x[j]-w2;						\
									\
	if(flgr_get_array_##dtype(cont_ptr,j) == 0) {			\
									\
	  flgr2d_set_data_array_##dtype(label_ptr,n,m,			\
					*cont_center_ptr);		\
									\
	  newcolor = flgr2d_get_data_array_##dtype(src_ptr,n,m);	\
									\
	  if(newcolor<i) {						\
	    newcolor=i+1;						\
	    while(newcolor<NB_FIFO-1) {					\
	      if(flgr_fifo_get_size(fifo+newcolor)!=0) break;		\
	      newcolor++;						\
	    }								\
	  }/*if the fifo priority have already been computed*/		\
									\
	  flgr_fifo_push(fifo+newcolor,0,n,m);				\
									\
	}/*if one neighbor is not labelized*/				\
      }/*for every neighbor*/						\
									\
    }/*while current fifo is not empty*/				\
  }/*for each fifo*/							\
  									\
  flgr2d_destroy(nhbOdd);						\
  flgr2d_destroy(nhbEven);						\
  flgr2d_destroy_neighbor_box(cont);					\
									\
  /* Destroy Priority Fifo */						\
  for(i=0 ; i<NB_FIFO; i++) {						\
    flgr_fifo_flush(fifo+i);						\
  }									\
									\
  return


void flgr2d_watershed_spp1_fgUINT8(FLGR_Data2D *imlabel, FLGR_Data2D *imsrc, FLGR_Connexity connexity) {
  FLGR_MACRO_WATERSHED_SPP1_2D(fgUINT8, FLGR_UINT8, 256);
}

void flgr2d_watershed_spp1_fgUINT16(FLGR_Data2D *imlabel, FLGR_Data2D *imsrc, FLGR_Connexity connexity) {
  FLGR_MACRO_WATERSHED_SPP1_2D(fgUINT16, FLGR_UINT16, 65536);
}



//!@}
